package com.skyworth.ui.customview;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.skyworth.util.SystemUtil;
import com.skyworth.util.Util;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by lu on 15-3-10.
 */
public class SlideFocusView extends FrameLayout {
    public Context context = null;

    public static interface ISlideFocusView {
        void initSlideFocusView(SlideFocusView parent);
    }

    /**
     * 焦点移动状态监听接口，目前只支持开始和结束
     */
    public interface OnMoveStateListener{
        public void beginMove();
        public void endMove();
    }

    /**
     * 设置监听焦点移动状态
     * @param listener 监听
     */
    public void setMoveStateListener(OnMoveStateListener listener){
        focusView.setMoveStateListener(listener);
    }




    public static class FocusView extends FrameLayout {
        private int posX, posY;
        private int destWidth, destHeight;
        private boolean executeAnim = true;
        private Context context = null;
        private OnMoveStateListener moveStateListener = null;
        private int bgId = 0;
        private Drawable bgDrawable = null;
        private View lastFocus = null;
        private boolean stopMoveOnce = false;
        private boolean focusAnimation = true;
        private boolean forceStopAnimation = !SystemUtil.isHighPerformance();
        public void setMoveStateListener(OnMoveStateListener listener){
            this.moveStateListener = listener;
        }

        public FocusView(Context context) {
            super(context);
            this.context = context;
            // TODO Auto-generated constructor stub
        }

        // 移动到指定位置
        public void changeFocusPos(int posX, int posY, int destWidth, int destHeight) {
            if (stopMoveOnce){
                stopMoveOnce = false;
                return;
            }
            this.posX = posX;
            this.posY = posY;
            this.destWidth = destWidth;
            this.destHeight = destHeight;
            Log.i("focuspos","x " + posX + " y " + posY + " w " + destWidth + " h " + destHeight);
            beginAnimation();
            //initStep();
            //invalidate();
        }

        public void stopMoveOnce(){
            stopMoveOnce = true;
        }

        @Override
        public void setBackgroundResource(int resid) {
            bgId = resid;
            if (lastFocus != null)
                lastFocus.setBackgroundResource(resid);
            executeAnim = false;
            bgDrawable = null;
        }

        @Override
        public void setBackgroundDrawable(Drawable background) {
            bgDrawable = background;
            if (lastFocus != null)
                lastFocus.setBackgroundDrawable(bgDrawable);
            executeAnim = false;
            bgId = 0;
        }

        private void startAlphaAnimation(View v, float from, float to, long during, Animator.AnimatorListener listener){
            ObjectAnimator animator = ObjectAnimator.ofFloat(v,"alpha",from,to);
            animator.setDuration(during);
            if (listener != null)
                animator.addListener(listener);
            animator.start();
        }


        public void moveFocusByCurrent(int x,int y){
            if (stopMoveOnce){
                stopMoveOnce = false;
                return;
            }
            posX += x;
            posY += y;
            beginAnimation();
        }

        public void moveFocusByCurrent(int x,int y, int w,int h){
            if (stopMoveOnce){
                stopMoveOnce = false;
                return;
            }
            posX += x;
            posY += y;
            destWidth += w;
            destHeight += h;
            beginAnimation();
        }

        private void beginAnimation() {
            if (lastFocus != null) {
                if (!forceStopAnimation && executeAnim && focusAnimation) {
                    startAlphaAnimation(lastFocus, 1.0f, 0.0f, 200, null);
                }else{
                    lastFocus.clearAnimation();
                    lastFocus.setVisibility(View.GONE);
                }
            }
            for(int i = 0; i < getChildCount() - 3; i++){
                removeView(getChildAt(i));
            }
            View focus = new ImageView(context);
            focus.setLayoutParams(new LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            Log.i("count","focus count is " + getChildCount());
            addView(focus);
            focus.setVisibility(View.VISIBLE);
            if (bgDrawable != null)
                focus.setBackgroundDrawable(bgDrawable);
            else if (bgId != 0)
                focus.setBackgroundResource(bgId);
            setFocusPos(focus,posX, posY, destWidth, destHeight);
            lastFocus = focus;
        }

        // 直接设置位置到指定位
        public void setFocusPos(final View view, int posX, int posY, int destWidth, int destHeight) {
            LayoutParams frameParams = (LayoutParams) view.getLayoutParams();
            frameParams.leftMargin = posX;
            frameParams.topMargin = posY;
            frameParams.width = destWidth;
            frameParams.height = destHeight;
            view.setLayoutParams(frameParams);
            if (!forceStopAnimation && executeAnim && focusAnimation){
                startAlphaAnimation(view, 0.0f, 1.0f, 200, new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        if (moveStateListener != null)
                            moveStateListener.beginMove();
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (moveStateListener != null)
                            moveStateListener.endMove();
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });
            }else{
                executeAnim = true;
                view.clearAnimation();
                view.setVisibility(View.VISIBLE);
                if (view.getAlpha() != 1.0f)
                    view.setAlpha(1.0f);

            }

        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            // TODO Auto-generated method stub
            initStep();
            super.onSizeChanged(w, h, oldw, oldh);
        }

        private void initStep() {

        }
    }

    /**
     * 控制焦点相对于view放大或者缩小的距离
     */
    public static class FocusViewRevision {
        public int left, top,right,bottom;

        public FocusViewRevision(int left, int top,int right,int bottom) {
            this.left = left;
            this.top = top;
            this.right = right;
            this.bottom = bottom;
        }
    }

    private abstract class IEvent<V, T> {
        protected final Map<V, T> eventListenerMap = new HashMap<V, T>();

        public void registerViewWithoutEvent(View view, FocusViewRevision rev) {
            if (rev != null) {
                synchronized (revMap) {
                    revMap.put(view, rev);
                }
            }
        }

        public void registerView(V view) {
            registerView(view, null, null);
        }

        public void registerView(V view, FocusViewRevision rev) {
            registerView(view, rev, null);
        }

        public void registerView(V view, FocusViewRevision rev, T listener) {
            if (rev != null) {
                synchronized (revMap) {
                    revMap.put(view, rev);
                }
            }
            if (listener != null) {
                synchronized (eventListenerMap) {
                    eventListenerMap.put(view, listener);
                }
            }
        }

        public void clearViewEventListener(V view) {
            if (view != null) {
                synchronized (eventListenerMap) {
                    eventListenerMap.remove(view);
                }
            }
        }
    }

    public class FocusChangedEvent extends IEvent<View, OnFocusChangeListener> implements
            OnFocusChangeListener {
        @Override
        public void registerView(View view, FocusViewRevision rev, OnFocusChangeListener listener) {
            view.setOnFocusChangeListener(this);
            super.registerView(view, rev, listener);
        }

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            // TODO Auto-generated method stub
            OnFocusChangeListener listener = null;
            if(hasFocus)
                updateFocusView(v);
            synchronized (eventListenerMap) {
                listener = eventListenerMap.get(v);
            }
            if (listener != null)
                listener.onFocusChange(v, hasFocus);

        }
    }

    public class ItemSelectedEvent extends IEvent<AdapterView<?>, OnItemSelectedListener> implements
            OnItemSelectedListener {
        @Override
        public void registerView(AdapterView<?> view, FocusViewRevision rev,
                                 OnItemSelectedListener listener) {
            view.setOnItemSelectedListener(this);
            super.registerView(view, rev, listener);
        }

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            OnItemSelectedListener listener = null;
            synchronized (eventListenerMap) {
                listener = eventListenerMap.get(parent);
            }
            if (listener != null)
                listener.onItemSelected(parent, view, position, id);
            if (view == null)
                return;
            updateFocusView(parent,view);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            // TODO Auto-generated method stub
            OnItemSelectedListener listener = null;
            synchronized (eventListenerMap) {
                listener = eventListenerMap.get(parent);
            }
            if (listener != null)
                listener.onNothingSelected(parent);
        }
    }

    private final Map<Object, FocusViewRevision> revMap = new HashMap<Object, FocusViewRevision>();

    protected FocusView focusView = null;
    private View currentFocusedView = null;
    public final FocusChangedEvent focusChangedEvent = new FocusChangedEvent();
    public final ItemSelectedEvent itemSelectedEvent = new ItemSelectedEvent();

    /**
     * @param context
     * @param focusDrawable 默认焦点
     */
    public SlideFocusView(Context context, int focusDrawable) {
        super(context);
        this.context = context;
        Util.instence(context);
        focusBg = focusDrawable;
        setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        focusView = new FocusView(context);
        focusView.setBackgroundResource(focusDrawable);
        focusView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT));
        focusView.setFocusable(false);
        focusView.setFocusableInTouchMode(false);
        addView(focusView);
    }


    private int focusBg = 0;


    /**
     * 改变焦点样式
     * @param id 焦点id
     */
    public void changeFocusBg(int id){
        focusBg = id;
        focusView.setBackgroundResource(id);
    }

    public void changeFocusBg(Drawable drawable){
        focusView.setBackgroundDrawable(drawable);
    }


    /**
     * 判断当前焦点和参数传递的id是否一致
     * @param id 需要判断的id
     * @return
     */
    public boolean isSameFocusBg(int id){
        if (id == focusBg)
            return true;
        return false;
    }

    public void initChildView(ISlideFocusView i) {
        i.initSlideFocusView(this);
    }

    public void updateFocusView(View v) {
        FocusViewRevision rev = null;
        synchronized (revMap) {
            rev = revMap.get(v);
        }
        updateFocusView(v, rev);
    }

    private void updateFocusView(View parent,View v){
        FocusViewRevision rev = null;
        synchronized (revMap) {
            rev = revMap.get(parent);
        }
        updateFocusView(v,rev);
    }

    private void updateFocusView(View v, FocusViewRevision rev) {
        final int[] to = new int[2];
        v.getLocationInWindow(to);
        int _focusViewWidth = v.getWidth();
        int _focusViewHeight = v.getHeight();
        if (rev != null) {
            _focusViewWidth += (rev.left + rev.right);
            _focusViewHeight += (rev.top + rev.bottom);
            to[0] -= rev.left;
            to[1] -= rev.top;
        }
        Log.i("OOO", "to:" + to[0] + "," + to[1] + " view : " + v.toString());
        focusView.changeFocusPos(to[0], to[1], _focusViewWidth, _focusViewHeight);
    }

    /**
     * 调用此方法后下一次焦点移动将没有动画效果
     */
    public void stopAnimationOnce(){
        focusView.executeAnim = false;
    }



    /**
     * 手动移动焦点到特定的view
     * @param view 需要移动焦点的view
     * @param revision 焦点框扩展大小
     */
    public void moveFocusTo(View view,FocusViewRevision revision){
        updateFocusView(view,revision);
    }

    /**
     * 相对于目前的焦点移动焦点框
     * @param x 水平距离
     * @param y 垂直距离
     */
    public void moveFocusByCurrent(int x,int y){
        focusView.moveFocusByCurrent(x,y);
    }

    public void moveFocusByCurrent(int x, int y,int w,int h){
        focusView.moveFocusByCurrent(x,y,w,h);
    }

    public void moveFocusTo(Rect rect){
        focusView.changeFocusPos(rect.left,rect.top,rect.width(),rect.height());
    }

    public FocusView getFocusView(){
        return focusView;
    }

    public void setFocusAnimation(boolean animation){
        focusView.focusAnimation = animation;
    }
}
